package com.the_last.config;

import com.the_last.constant.OrderConstant;
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * RabbitMQ配置类
 * 配置订单超时队列、预约超时队列和死信队列，实现自动超时处理功能
 * 
 * @author zhanghaifeng
 */
@Configuration
public class RabbitConfig {
    
    // ========== 订单相关队列配置 ==========
    // 订单延时队列（等待支付的订单队列）
    public static final String ORDER_DELAY_QUEUE = "order.delay.queue";
    // 订单超时处理队列（死信队列，处理超时订单）
    public static final String ORDER_TIMEOUT_QUEUE = "order.timeout.queue";
    // 订单超时交换器
    public static final String ORDER_TIMEOUT_EXCHANGE = "order.timeout.exchange";
    // 订单延时交换器
    public static final String ORDER_DELAY_EXCHANGE = "order.delay.exchange";
    
    // ========== 预约相关队列配置 ==========
    // 预约延时队列（等待使用的预约队列）
    public static final String RESERVATION_DELAY_QUEUE = "reservation.delay.queue";
    // 预约超时处理队列（死信队列，处理超时预约）
    public static final String RESERVATION_TIMEOUT_QUEUE = "reservation.timeout.queue";
    // 预约超时交换器
    public static final String RESERVATION_TIMEOUT_EXCHANGE = "reservation.timeout.exchange";
    // 预约延时交换器
    public static final String RESERVATION_DELAY_EXCHANGE = "reservation.delay.exchange";
    
    /**
     * 声明订单延时交换器
     */
    @Bean
    public DirectExchange orderDelayExchange() {
        return new DirectExchange(ORDER_DELAY_EXCHANGE, true, false);
    }
    
    /**
     * 声明订单超时交换器
     */
    @Bean
    public DirectExchange orderTimeoutExchange() {
        return new DirectExchange(ORDER_TIMEOUT_EXCHANGE, true, false);
    }
    
    /**
     * 声明订单延时队列，配置死信交换器和TTL
     * 订单在此队列中等待指定时间后会自动转发到超时处理队列
     */
    @Bean
    public Queue orderDelayQueue() {
        return QueueBuilder.durable(ORDER_DELAY_QUEUE)
                // 设置消息TTL（订单超时时间）
                .ttl(OrderConstant.ORDER_TIMEOUT_MILLIS)
                // 设置死信交换器
                .deadLetterExchange(ORDER_TIMEOUT_EXCHANGE)
                // 设置死信路由键
                .deadLetterRoutingKey(ORDER_TIMEOUT_QUEUE)
                .build();
    }
    
    /**
     * 声明订单超时处理队列
     */
    @Bean
    public Queue orderTimeoutQueue() {
        return QueueBuilder.durable(ORDER_TIMEOUT_QUEUE).build();
    }
    
    /**
     * 绑定订单延时队列到延时交换器
     */
    @Bean
    public Binding bindingOrderDelayQueue() {
        return BindingBuilder.bind(orderDelayQueue())
                .to(orderDelayExchange())
                .with(ORDER_DELAY_QUEUE);
    }
    
    /**
     * 绑定订单超时队列到超时交换器
     */
    @Bean
    public Binding bindingOrderTimeoutQueue() {
        return BindingBuilder.bind(orderTimeoutQueue())
                .to(orderTimeoutExchange())
                .with(ORDER_TIMEOUT_QUEUE);
    }
    
    // ========== 预约相关队列和交换器配置 ==========
    
    /**
     * 声明预约延时交换器
     */
    @Bean
    public DirectExchange reservationDelayExchange() {
        return new DirectExchange(RESERVATION_DELAY_EXCHANGE, true, false);
    }
    
    /**
     * 声明预约超时交换器
     */
    @Bean
    public DirectExchange reservationTimeoutExchange() {
        return new DirectExchange(RESERVATION_TIMEOUT_EXCHANGE, true, false);
    }
    
    /**
     * 声明预约延时队列，配置死信交换器
     * 预约在此队列中等待到结束时间后会自动转发到超时处理队列
     * 注意：预约的超时时间是动态计算的，不像订单那样使用固定TTL
     * 所以这里不设置TTL，而是在发送消息时设置每条消息的TTL
     */
    @Bean
    public Queue reservationDelayQueue() {
        return QueueBuilder.durable(RESERVATION_DELAY_QUEUE)
                // 不设置固定TTL，使用消息级别的TTL
                // 设置死信交换器
                .deadLetterExchange(RESERVATION_TIMEOUT_EXCHANGE)
                // 设置死信路由键
                .deadLetterRoutingKey(RESERVATION_TIMEOUT_QUEUE)
                .build();
    }
    
    /**
     * 声明预约超时处理队列
     */
    @Bean
    public Queue reservationTimeoutQueue() {
        return QueueBuilder.durable(RESERVATION_TIMEOUT_QUEUE).build();
    }
    
    /**
     * 绑定预约延时队列到延时交换器
     */
    @Bean
    public Binding bindingReservationDelayQueue() {
        return BindingBuilder.bind(reservationDelayQueue())
                .to(reservationDelayExchange())
                .with(RESERVATION_DELAY_QUEUE);
    }
    
    /**
     * 绑定预约超时队列到超时交换器
     */
    @Bean
    public Binding bindingReservationTimeoutQueue() {
        return BindingBuilder.bind(reservationTimeoutQueue())
                .to(reservationTimeoutExchange())
                .with(RESERVATION_TIMEOUT_QUEUE);
    }
}